gdk/wayland: Defer processing of globals closures
authorRobert Mader <robert.mader@posteo.de>
Sat, 27 Mar 2021 14:48:00 +0000 (15:48 +0100)
committerRobert Mader <robert.mader@posteo.de>
Tue, 30 Mar 2021 13:20:00 +0000 (15:20 +0200)
... until all globals have been received.

The dependency tracking introduced in 4e9be39518 only allows to
specify required globals and processes the closures as soon as
the requirements have been met. There are, however, also optional
dependencies - most notably the primary_selection protocol.
Currently we rely on the fact that compositors like Mutter announce
it before `wl_seat`, even though the order is not specified in
the spec.

Process globals closures only after all globals have been announced,
so optional dependencies can be accommodated.

Closes https://gitlab.gnome.org/GNOME/gtk/-/issues/3791

gdk/wayland/gdkdisplay-wayland.c

index 03a38be862833c4f0692730af1ef0b7d9ccefc06..cc4583658b19693f1d77fae8e5267681f22d07ee 100644 (file)
@@ -488,26 +488,19 @@ gdk_registry_handle_global (void               *data,
     }
   else if (strcmp (interface, "wl_seat") == 0)
     {
+      SeatAddedClosure *closure;
       static const char *required_device_manager_globals[] = {
         "wl_compositor",
         "wl_data_device_manager",
         NULL
       };
 
-      if (has_required_globals (display_wayland,
-                                required_device_manager_globals))
-        _gdk_wayland_display_add_seat (display_wayland, id, version);
-      else
-        {
-          SeatAddedClosure *closure;
-
-          closure = g_new0 (SeatAddedClosure, 1);
-          closure->base.handler = seat_added_closure_run;
-          closure->base.required_globals = required_device_manager_globals;
-          closure->id = id;
-          closure->version = version;
-          postpone_on_globals_closure (display_wayland, &closure->base);
-        }
+      closure = g_new0 (SeatAddedClosure, 1);
+      closure->base.handler = seat_added_closure_run;
+      closure->base.required_globals = required_device_manager_globals;
+      closure->id = id;
+      closure->version = version;
+      postpone_on_globals_closure (display_wayland, &closure->base);
     }
   else if (strcmp (interface, "wl_data_device_manager") == 0)
     {
@@ -586,8 +579,6 @@ gdk_registry_handle_global (void               *data,
 
   g_hash_table_insert (display_wayland->known_globals,
                        GUINT_TO_POINTER (id), g_strdup (interface));
-
-  process_on_globals_closures (display_wayland);
 }
 
 static void
@@ -679,8 +670,13 @@ _gdk_wayland_display_open (const char *display_name)
 
   display_wayland->wl_registry = wl_display_get_registry (display_wayland->wl_display);
   wl_registry_add_listener (display_wayland->wl_registry, &registry_listener, display_wayland);
+  if (wl_display_roundtrip (display_wayland->wl_display) < 0)
+    {
+      g_object_unref (display);
+      return NULL;
+    }
 
-  _gdk_wayland_display_async_roundtrip (display_wayland);
+  process_on_globals_closures (display_wayland);
 
   /* Wait for initializing to complete. This means waiting for all
    * asynchronous roundtrips that were triggered during initial roundtrip. */